package model;

import java.io.*;
import java.util.StringTokenizer;
import twitter4j.*;
import twitter4j.auth.*;

/**
 * @author Manseer Marcel  
 * @author Plavsic Maja
 * @author Pretsch Paul
 */
public class Authenticator {

	/**
	 * Log in to a twitter account using the REST API
	 * 
	 * @param userId UserID from a twitter user
	 * @return an instance of {@link twitter4j.Twitter Twitter} authenticated with to the user 
	 */
	public static Twitter authenticateStatic(long userId)
	{
		Twitter twitter = new TwitterFactory().getInstance();

		try	{
			AccessToken accessToken = loadAccessToken(userId);
			authenticate(twitter, accessToken, userId);
			storeAccessToken(twitter.getId(), twitter.getOAuthAccessToken());
			
			System.out.println("logged in as @" + twitter.verifyCredentials().getName());
		} catch (TwitterException te) {
			if (401 == te.getStatusCode()) {
				System.out.println("cant authenticate as " + userId);
			} 
			te.printStackTrace();
			
			twitter = null;
		}
		
		return twitter;
	}


	/**
	 * Log in to a twitter account using the Streaming API
	 * 
	 * @param userId UserID from a twitter user
	 * @return an instance of {@link twitter4j.TwitterStream TwitterStream} authenticated with to the user 
	 */
	public static TwitterStream authenticateStream(long userId)
	{
		TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
		
		try	{
			AccessToken accessToken = loadAccessToken(userId);
			authenticate(twitterStream, accessToken, userId);
			storeAccessToken(twitterStream.getId(), twitterStream.getOAuthAccessToken());			
		} catch (TwitterException te) {
			if (401 == te.getStatusCode()) {
				System.out.println("cant authenticate as " + userId);
			} 
			te.printStackTrace();
			
			twitterStream = null;
		}
		
		return twitterStream;
	}
	
	/**
	 * @param auth any object supporting {@link twitter4j.auth.OAuthSupport OAuthSupport} for authetication
	 * @param accessToken access token of the user
	 * @param userId UserID of the twitter user
	 * @throws TwitterException
	 */
	private static void authenticate(OAuthSupport auth, AccessToken accessToken, long userId) throws TwitterException
	{
		auth.setOAuthConsumer("p7vGRtFlJy9skXJK5i5Wjg",
				"01lS8iFxLePNZE0qf6uXJSFftfmPEHl3YFbSOwwfp4");
		
		try {
			if (accessToken != null) {
				auth.setOAuthAccessToken(accessToken);
			} else {
				RequestToken requestToken = auth.getOAuthRequestToken();
				BufferedReader br = new BufferedReader(new InputStreamReader(
						System.in));
				while (null == accessToken) {
					System.out
							.println("Open the following URL and grant access to your account:");
					System.out.println(requestToken.getAuthorizationURL());
					System.out
							.print("Enter the PIN(if aviailable) or just hit enter.[PIN]:");
					String pin = br.readLine();
					try {
						if (pin.length() > 0) {
							accessToken = auth.getOAuthAccessToken(requestToken,
									pin);
						} else {
							accessToken = auth.getOAuthAccessToken();
						}
					} catch (TwitterException te) {
						if (401 == te.getStatusCode()) {
							System.out.println("Unable to get the access token.");
						} else {
							te.printStackTrace();
						}
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("cant read pin");
		}		
	}
	
	/**
	 * stores the access token for a specific twitter user
	 * 
	 * @param userId
	 * @param accessToken
	 */
	private static void storeAccessToken(long userId, AccessToken accessToken) {
	    try {
	    	String token = String.format("%d %s %s", userId, accessToken.getToken(), accessToken.getTokenSecret());
	    	boolean tokenFound = false;
	    	
	    	// search token in file in existing file
	    	if (new File("accessTokens.txt").exists()) {
				BufferedReader br = new BufferedReader(new FileReader("accessTokens.txt"));
				String line;
				while (((line = br.readLine()) != null) && !tokenFound) {
					tokenFound = line.equals(token); 
				}
				br.close();		
	    	}
	    	
			// write new token to file
			if (!tokenFound) {
		        BufferedWriter out = new BufferedWriter(new FileWriter("accessTokens.txt", true));
		        out.write(token);
		        out.newLine();
		        out.close();
			}
	    } 
	    catch (IOException e) 
	    { 
	    	e.printStackTrace();
	    }		
	}

	/**
	 * laod the access token for a specific twitter user
	 * 
	 * @param userId
	 * @return {@link twitter4j.auth.AccessToken AccessToken}
	 */
	private static AccessToken loadAccessToken(long userId) {
		AccessToken accessToken = null;
		StringTokenizer parser = null;
		
		BufferedReader br;
		try {
			br = new BufferedReader(new FileReader("accessTokens.txt"));
			String line;
			while (((line = br.readLine()) != null) && (accessToken == null)) {
				parser = new StringTokenizer(line);
				if (parser.countTokens() == 3) {
					long usedId = Long.parseLong(parser.nextToken());
					String token = parser.nextToken();
					String tokenSecret = parser.nextToken();
					if ((userId == Long.MIN_VALUE) || (userId == usedId)) {
						accessToken = new AccessToken(token, tokenSecret);
					}
				}
			}
			br.close();		
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
			e.printStackTrace();
		}
		return accessToken;
	}
}
